package com.bxl.chooser.oper.impl;

import com.bxl.chooser.bean.AppInfo;
import com.bxl.chooser.bean.ChooseMsg;
import com.bxl.chooser.bean.ChooseResponseMsg;
import com.bxl.chooser.context.ChooserContext;
import com.bxl.chooser.factory.ChooseMsgFactory;
import com.bxl.chooser.oper.IOperSv;
import com.bxl.netty.rpc.common.message.PackageMsg;
import org.apache.commons.lang3.StringUtils;

/**
 * 选举服务
 *
 * @author baixl
 * @date 2021/3/25
 */
public class ChooserService implements IOperSv<ChooseResponseMsg> {
    @Override
    public ChooseResponseMsg oper(PackageMsg<ChooseMsg> msg, ChooserContext context) {
        ChooseMsg chooseMsg = msg.getContent();
        AppInfo appInfo = context.getAppInfo();
        //任期比较 维护一个是否有leader的状态，避免某一台主机不稳定时，频繁的切换leader
        //例如  follower断网好了之后，因为没有心跳信息，会发起自己的选举，如果此时term是最新的且索引满足要求，会选举成功的。
        //维护leader状态后，拒绝有leader的选举。但是 有一个问题。如果leader分区，由于每个follower的时间间隔不一样，要等二分之一的主机都没有收到
        //心跳的时候 才能选举出新的leader。
        if (chooseMsg.getTerm() >= appInfo.getTerm() && !context.getHasLeader()) {
            //日志比较
            if (chooseMsg.getIndex() >= appInfo.getLogIndex()) {
                if (StringUtils.isEmpty(appInfo.getVotedFor()) || appInfo.getVotedFor().equals(chooseMsg.getVotedFor())) {
                    //返回投票成功
                    if (chooseMsg.getTerm() > appInfo.getTerm()) {
                        appInfo.setTerm(chooseMsg.getTerm());
                    }
                    if(appInfo.getState() == AppInfo.AppState.LEADER){
                        context.degraded();
                    }
                    System.out.println(String.format("chooser %s as leader,term is %s",chooseMsg.getAppId(),chooseMsg.getTerm()));
                    return ChooseMsgFactory.createChooseResponseMsg(chooseMsg.getTerm(), true);
                }
            }
        }
        System.out.println(String.format("refuse %s as leader,term is %s",chooseMsg.getAppId(),chooseMsg.getTerm()));
        return ChooseMsgFactory.createChooseResponseMsg(appInfo.getTerm(), false);
    }
}
